using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using System.Diagnostics;
using System.Reflection;

namespace IHC_InspectorExpress.Modelo
{
    //[Serializable]
    public class Sistema
    {
        private String nombreSistema;
        private int maxElementos;

        public Sistema ()
        {
            this.nombreSistema = "";
        }

        public Sistema(String sistema,int melementos)
        {
            this.nombreSistema = sistema;
            this.maxElementos= melementos;
        }
        public Sistema(String sistema)
        {
            this.nombreSistema = sistema;
        }
        public String NombreSistema
        {
            get { return nombreSistema; }
            set { nombreSistema = value; }
        }

        public int MaxElementos
        {
            get { return maxElementos; }
            set { maxElementos = value; }
        }
        /// <summary>
        /// agregarSistema:
        /// Agrega un nuevo sistema a IE
        /// Recibe: un DTOSistema
        /// Retorna: int - Codigo de resultado de la operacion:
        ///     0   correcto
        ///     1   El nombre del sistema ya existe
        ///     -1  Error desconocido
        /// </summary>
        //[XmlIgnore]
        public int agregarSistema(DTOSistema dto_sistema)
        {
            int resultado = 0;
            try
            {
                //obtengo la lista de sistemas y tareas
                ListaSistema sistemas = obtenerSistemas();
                ListaTarea tareas = obtenerTareas();
                //reviso si no existe el nuevo sistema a agregar ya en la aplicacion
                bool existe_sistema = false;
                foreach (Sistema sistema in sistemas.Sistemas)
                {
                    //transforma a mayuscula y compara ambos
                    if (sistema.NombreSistema.ToUpper().CompareTo(dto_sistema.Nombre.ToUpper())==0)
                    {
                        existe_sistema = true;
                        resultado = 1;
                    }
                }
                if (!existe_sistema)
                {
                    if (sistemas != null && tareas != null)
                    {
                        //agrego nombre a la lista
                        sistemas.Sistemas.Add(new Sistema(dto_sistema.Nombre,dto_sistema.MaxElementos));
                        //agrego las tareas a la lista
                        foreach (string tarea in dto_sistema.Tareas)
                        {
                            Tarea otarea = new Tarea(tarea, "", new Sistema(dto_sistema.Nombre), null);
                            tareas.Tareas.Add(otarea);
                        }
                        //guardo la nueva lista de sistemas
                        bool exito = guardarSistemas(sistemas);
                        if (!exito) resultado = -1;
                        //guardo la nueva lista de tareas
                        exito = guardarTareas(tareas);
                        if (!exito) resultado = -1;
                        else resultado = 0;
                    }
                    else
                    {
                        resultado = -1;
                    }
                }                
                
            }
            catch (Exception ex)
            {
                resultado = -1;
            }
            return resultado;
        }
        
        /// <summary>
        /// Obtiene una lista de sistema que actualmente estan el archivo
        /// Sistemas.xml
        /// </summary>
        /// <returns>un objeto ListaSistema con los sistemas</returns>
        private ListaSistema obtenerSistemas()
        {
            try
            {
                String filename = "Datos/Sistemas.xml";
                StreamReader myStream = new StreamReader(filename);
                ListaSistema sistemas = ListaSistema.getInstanciaSistema();
                if (myStream != null)
                {
                    Debug.WriteLine(myStream.ReadLine());
                    XmlTextReader xr = new XmlTextReader(myStream);
                    XmlSerializer xs = new XmlSerializer(typeof(ListaSistema));
                    
                    Object c;

                    if (xs.CanDeserialize(xr))
                    {
                        // Deserializar los datos de entrada
                        c = xs.Deserialize(xr);

                        // obtener la definicion del objeto
                        Type t = sistemas.GetType();

                        // Obtener un array con los atributos recuperados
                        PropertyInfo[] properties = t.GetProperties();

                        // Recorrer los atributos, y asignarlos a la estructura de Heuristica
                        foreach (PropertyInfo p in properties)
                        {
                            p.SetValue(sistemas, p.GetValue(c, null), null);
                        }
                    }

                    //Se cierra el stream y el lector
                    xr.Close();
                    myStream.Close();
                }
                return sistemas;
            }
            catch (Exception ex)
            {
                return null;
            }            
        }
        
        /// <summary>
        /// Guarda la lista de sistemas. Actualiza el archivo si es que hay nuevos
        /// </summary>
        /// <param name="sistemas">lista de sistemas</param>
        /// <returns>un booleano indicando si hay error o no en la operacion</returns>
        public bool guardarSistemas(ListaSistema sistemas) 
        {
            try
            {
                Stream myStream;
                string filename = "Datos/Sistemas.xml";
                myStream = File.OpenWrite(filename); //Se abre un archivo para guardar la estructura
                if (myStream != null)
                {                    
                    //Type[] serie = new Type[1];
                    //serie[0] = usuario.GetType();
                    XmlSerializer formatter = new XmlSerializer(typeof(ListaSistema)); //cambiar this
                    formatter.Serialize(myStream, sistemas); //Se guarda en el archivo //cambiar this
                    myStream.Close(); //Se cierra el stream                    
                }
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// Obtiene una lista con todas las tareas de todos los sistema a evaluar
        /// </summary>
        /// <returns>una lista con las tareas</returns>
        public ListaTarea obtenerTareas()
        {
            try
            {
                String filename = "Datos/Tareas.xml";
                StreamReader myStream = new StreamReader(filename);
                ListaTarea tareas = new ListaTarea();
                if (myStream != null)
                {
                    XmlTextReader xr = new XmlTextReader(myStream);
                    XmlSerializer xs = new XmlSerializer(typeof(ListaTarea));

                    Object c;

                    if (xs.CanDeserialize(xr))
                    {
                        // Deserializar los datos de entrada
                        c = xs.Deserialize(xr);

                        // obtener la definicion del objeto
                        Type t = typeof(ListaTarea);

                        // Obtener un array con los atributos recuperados
                        PropertyInfo[] properties = t.GetProperties();

                        // Recorrer los atributos, y asignarlos a la estructura de Heuristica
                        foreach (PropertyInfo p in properties)
                        {
                            p.SetValue(tareas, p.GetValue(c, null), null);
                        }
                    }

                    //Se cierra el stream y el lector
                    xr.Close();
                    myStream.Close();
                }
                return tareas;
            }
            catch (Exception ex)
            {
                return null;
            } 
        }


        /// <summary>
        /// Guarda la lista de tareas. Actualiza el archivo si es que hay nuevos
        /// </summary>
        /// <param name="tareas">lista de tareas</param>
        /// <returns>un booleano indicando si hay error o no en la operacion</returns>
        public bool guardarTareas(ListaTarea tareas)
        {
            try
            {
                Stream myStream;
                string filename = "Datos/Tareas.xml";
                myStream = File.OpenWrite(filename); //Se abre un archivo para guardar la estructura
                if (myStream != null)
                {                    
                    XmlSerializer formatter = new XmlSerializer(typeof(ListaTarea)); 
                    formatter.Serialize(myStream, tareas); //Se guarda en el archivo 
                    myStream.Close(); //Se cierra el stream                    
                }
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// DTOSistema:
        /// Almacena los datos de un sistema en particular. 
        /// Nombre y la lista de tareas
        /// </summary>
        //[XmlIgnore]
        public class DTOSistema
        {
            private string nombre;
            private int maxElementos;
            private List<string> tareas;

            public string Nombre
            {
                get { return nombre; }
                set { nombre = value; }
            }

            public int MaxElementos
            {
                get { return maxElementos; }
                set { maxElementos = value; }
            }

            public List<string> Tareas
            {
                get { return tareas; }
                set { tareas = value; }
            }            
        }
    }
}
